home *** CD-ROM | disk | FTP | other *** search
- |
- | syscall: interface for system calls. The following entry points are
- | defined:
- | _mint_bios: entry point for the BIOS calls (trap #13)
- | _mint_xbios: entry point for XBIOS calls (trap #14)
- | _mint_dos: entry point for GEMDOS calls (trap #1)
- | _sig_return: user signal handlers return to this routine (see signal.c)
- | it is responsible for restoring the kernel's old context
- | via the Psigreturn() system call
- | _lineA0: calls the line A initialize routine
- | _call_aes: calls the GEM AES
- | _callout: call an external function, after first making sure that all
- | registers are saved
- |
- | external variables referenced:
- | _bios_tab, _bios_max:
- | table of entry points for BIOS routines, max # of routine
- | _xbios_tab, _xbios_max:
- | ditto for XBIOS
- | _dos_tab, _dos_max:
- | ditto for GEMDOS
- | _curproc:
- | pointer to current process table entry, and hence to save area for
- | context (this is always the first entry in the PROC table).
- | _valid_return:
- | used to indicate to the kernel that a valid return from user mode
- | is taking place
- |
- | _bconbuf, _bconbsiz, _bconbdev:
- | 256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
- | there are that many bytes in _bconbuf waiting to be flushed. The
- | output is for device _bconbdev.
- |
- | The C function enter_kernel() is called on entry to the kernel, and the
- | function leave_kernel() is called on exit. These functions are responsible
- | for saving and restoring the various trap vectors, so that MiNT can trap
- | out to TOS directly, but programs can only trap to MiNT.
- |
- .globl _mint_bios, _mint_xbios
- .globl _mint_dos
- .globl _build_context
- .globl _restore_context
-
- .globl _curproc
- .globl _bios_tab, _bios_max
- .globl _xbios_tab, _xbios_max
- .globl _dos_tab, _dos_max
- .globl _bconbuf, _bconbsiz, _bconbdev
- .globl _bflush
-
- .data
- .comm syscall_tab, 4 | set to which table to use for the call
- .comm syscall_max, 4 | maximum valid number for this call
-
- .text
- .even
-
- _mint_dos:
- movel #_dos_tab, syscall_tab
- movew _dos_max, syscall_max
- bra _syscall
-
- _mint_xbios:
- movel #_xbios_tab, syscall_tab
- movew _xbios_max, syscall_max
- bra _syscall
-
- _mint_bios:
- |
- | Bconout() is noticeably slower under MiNT, so we do a bit of a kludge
- | and special case Bconout() so that it doesn't take so long. We
- | do this by buffering Bconout calls until either another kind of
- | system call or a context switch happens.
- |
- tstw _bconbdev | buffering on?
- bmi L_bios | if bconbdev < 0, no buffering
- btst #13, sp@ | test for user/super mode
- beq L_usr |
- lea sp@(6), a1 | supervisor mode: args on stack
- tstw 0x59e | test longframe
- beq L_check
- addql #2, a1 | stack is a bit bigger
- bra L_check
- L_usr:
- movel usp, a1 | user mode: args on user stack
- L_check:
- movew a1@, d0 | check command
- cmpw #3, d0 | Bconout?
- beq do_bconout | yes -- take some shortcuts
- | no -- fall through to the normal code
- L_bios:
- movel #_bios_tab, syscall_tab
- movew _bios_max, syscall_max
-
- _syscall:
- movel _curproc, d0
- addql #4, d0
- movel d0, sp@- | push pointer to syscall context save
- jsr _build_context
- |
- | copy parameters onto process stack. a1 was set by _build_context
- |
- L_copy:
- movel _curproc, a0
- movel a0@, a0 | fetch system call stack pointer
- lea a0@(-28), sp | this puts us in our private stack
- moveml a1@, d1-d7 | copy parameters from user stack
- moveml d1-d7, sp@ | to ours (build_context set a1)
- |
- jsr _enter_kernel | set up vectors appropriately
- |
- | check here to see if we need to flush the Bconout() buffers
- |
- tstw _bconbsiz | characters in buffer?
- beq L_noflush | nope: OK to proceed
- |
- | make sure we save syscall_tab and syscall_max
- |
- movel syscall_tab, sp@-
- movew syscall_max, sp@-
- jsr _bflush | flush the buffer
- movew sp@+, syscall_max
- movel sp@+, syscall_tab
-
- L_noflush:
- |
- | figure out which routine to call
- |
- clrl d0
- movew sp@, d0
- cmpw #-1, d0 | trapping with -1 means return
- bne check_max | the corresponding system table
- movel syscall_tab, d0
- bra out
- check_max:
- cmpw syscall_max, d0
- bge error
- addl d0,d0
- addl d0,d0 | multiply by 4
- movel syscall_tab, a0
- addl d0, a0
- movel a0@, a0
- cmpl #0, a0 | null entry means invalid call
- beq error
- addql #2, sp | pop function number off stack
- jsr a0@ | go do the call
- out:
- movel _curproc, a0
- movel d0, a0@(4) | set d0 in the saved context
- tstw _proc_clock | has process exceeded time slice?
- bne nosleep | no -- continue
- movew a0@(68), d0 | get saved status register
- btst #13, d0 | caller in supervisor mode?
- bne nosleep | yes -- don't interrupt
- sleep:
- jsr _preempt | does a sleep(READY_Q)
- nosleep:
- oriw #0x0700, sr | spl7()
- jsr _leave_kernel | restore vectors
- movel _curproc, a0
- pea a0@(4)
- jsr _restore_context | never returns
-
- |
- | we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
- | as appropriate, and letting them handle it -- that way, if the underlying
- | system has functions we don't know about, they still work
- |
-
- error:
- movel syscall_tab, a0
- cmpl #_xbios_tab, a0
- bne maybe_dos
- trap #14
- bra out
- maybe_dos:
- cmpl #_dos_tab, a0
- beq trap_1
- trap #13
- bra out
- trap_1:
- trap #1
- bra out
-
- |
- | sig_return: user signal handlers return to us. At that point, the
- | stack looks like this:
- | (sp) (long) signal number -- was a parameter for user routine
- |
- .globl _sig_return
- .globl _valid_return
- _sig_return:
- addql #4, sp | pop signal number
- movew #0x11a, sp@- | Psigreturn() system call
- movew #1, _valid_return | tell kernel it's us!
- trap #1
- | we had better not come back; if we did, something terrible
- | happened, and we might as well terminate
- movew #-998, sp@-
- movew #0x4c, sp@- | Pterm()
- trap #1
-
- |
- | bconout special code: on entry, a1 points to the stack the user
- | was using. If possible, we just buffer the output until later.
- |
-
- do_bconout:
- movew a1@(2), d0 | what device is this for?
- beq L_bios | don't buffer the printer
- cmpw _bconbdev, d0 | same device as is buffered?
- bne new_dev | no -- maybe we can't do this
- put_buf:
- movew a1@(4), d0 | get the character to output
- movew _bconbsiz, d1 | get index into buffer table
- cmpw #255, d1 | buffer full?
- beq L_bios | yes -- flush it out
- lea _bconbuf, a0
- addw d1, a0
- moveb d0, a0@ | store the character
- addqw #1, d1
- movew d1, _bconbsiz
- moveql #-1, d0 | return character output OK
- rte
-
- new_dev:
- tstw _bconbsiz | characters already in buffer?
- bne L_bios | yes: we can't buffer this one
- movew d0, _bconbdev | no: OK, we have a new device
- bra put_buf
- |
- |
- | _lineA0: MiNT calls this to get the address of the line A variables
- |
- .globl _lineA0
- _lineA0:
- moveml d2/a2, sp@- | save scratch registers
- .word 0xa000 | call the line A initialization routine
- moveml sp@+, d2/a2
- rts
-
- |
- | _call_aes: calls the GEM AES, using the control block passed as
- | a parameter. Used only for doing appl_init(), to see
- | if the AES is active yet
- |
- .globl _call_aes
- _call_aes:
- movel sp@(4), d1 | fetch pointer to parameter block
- movew #0xc8, d0 | magic number for AES
- moveml d2/a2, sp@- | save scratch registers
- trap #2
- moveml sp@+, d2/a2
- rts
-
-
- |
- | _callout: Call an external function, passing <32 bytes of arguments,
- | and return the value from the function. NOTE: we must be careful
- | to save all registers here!
- |
- .globl _callout
- _callout:
- lea sp@(8), a0 | pointer to args
- movel sp@(4), a1 | pointer to function
- moveml d2-d7/a2-a6, sp@- | save registers
- moveml a0@, d0-d7 | copy parameters
- lea sp@(-32), sp | NOTE: moveml auto-decrement
- moveml d0-d7, sp@ | changes the order of things
- movel a1@, a0 | get function address
- jsr a0@ | go do it
- addl #32, sp
- moveml sp@+, d2-d7/a2-a6 | restore reggies
- rts
-